﻿using Micro.Core.Packages;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Micro.Modules.Abstractions;
using Micro.AspNetCore;
using Micro.Utils;
using Micro.Utils.Constants;
using Micro.Core.Reflection;
using Micro.Extensions.DDD.Commands;
using Micro.Extensions.DDD.Events;

namespace Microsoft.Extensions.DependencyInjection
{
    public class IOCPack : BasePackage
    {
        public override int Order => 100;
        public override PackLevel Level => PackLevel.Business;

        public override IServiceCollection AddServices(IServiceCollection services)
        {
            AddModuleServices(services);
            return services;
        }

        /// <summary>
        /// 添记模块的服务
        /// </summary>
        /// <param name="provider"></param>
        private void AddModuleServices(IServiceCollection services)
        {
            IServiceProvider provider= services.BuildServiceProvider();
            var modules = provider.GetServices<IModule>();

            var prefix = ModuleConstant.PREFIX.IsNull() ? "" : $"{ModuleConstant.PREFIX}.";
            foreach (var module in modules)
            {
                //AppService
                var applicationName = $"{prefix}{string.Format(ModuleConstant.ApplicationDLLName, module.Code)}";
                var appServiceAssembly = module.Context.Get(applicationName);
                if (appServiceAssembly != null)
                    services.AddCustomServices(ServiceLifetime.Scoped, endsWith: "AppService", assemblys: appServiceAssembly);

                //Repository
                var InfrastructureName = $"{prefix}{string.Format(ModuleConstant.InfrastructureDLLName, module.Code)}";
                var infrastructureAssembly = module.Context.Get(InfrastructureName);
                if (infrastructureAssembly != null)
                    services.AddCustomServices(ServiceLifetime.Scoped, endsWith: "Repository", notEqualsArrys: new string[] { "IBaseRepository`1" }, assemblys: infrastructureAssembly);

                //Domain
                var domainName = $"{prefix}{string.Format(ModuleConstant.DomainDLLName, module.Code)}"; 
                var domainAssembly = module.Context.Get(applicationName);
                if (domainAssembly != null)
                    AddDomainServices(services);
            }
        }

        /// <summary>
        /// 添加domain层依赖注入
        /// </summary>
        /// <param name="services"></param>
        private void AddDomainServices(IServiceCollection services)
        {
            {
                //基类CommandHandler依赖注入
                var types = AssemblyManager.AllAssemblies.SelectMany(m => m.GetTypes().Where(t => t.IsClass && !t.IsAbstract && t.IsBaseOn<CommandHandler>() && t != typeof(CommandHandler))).ToArray();
                foreach (Type type in types)
                {
                    var interfaces = type.GetInterfaces();
                    if (interfaces != null)
                    {
                        foreach (var interfaceType in interfaces)
                            services.AddScoped(interfaceType, type);
                    }
                }
            }

            {
                //基类EventsHandler依赖注入
                var types = AssemblyManager.AllAssemblies.SelectMany(m => m.GetTypes().Where(t => t.IsClass && !t.IsAbstract && t.IsBaseOn<EventsHandler>() && t != typeof(EventsHandler))).ToArray();
                foreach (Type type in types)
                {
                    var interfaces = type.GetInterfaces();
                    if (interfaces != null)
                    {
                        foreach (var interfaceType in interfaces)
                            services.AddScoped(interfaceType, type);
                    }
                }
            }
        }

    }
}